<script setup>
import {getCurrentInstance, onMounted, ref, defineExpose} from 'vue'
import processApi from '@/api/process/processApi.js'
import {nanoid} from 'nanoid'
import JsonEditor from 'jsoneditor'
import 'jsoneditor/dist/jsoneditor.min.css'
import {message} from 'ant-design-vue'
import {Func} from './ParamDefineFunc.js'
import downloadUtil from '@/utils/downloadUtil'

const {proxy} = getCurrentInstance()

const tableRef = ref()
const props = defineProps([
	'params',
	'isViewBasicFieldFlag',
	'isViewArrayFlag',
	'isAddColumnFlag',
	'isUpdateColumnFlag',
	'isUpdateDefaultValueFlag',
	'isImportFlag',
	'isRemoveColumnFlag',
	'isAddChildrenColumnFlag',
	'isActionColumnFlag',
	'autoMappingFunc',
	'isViewClearMappingFlag',
	'isClearFlag',
	'defaultValueFlag',
	'height',
	'isViewAutoMappingFlag',
	'isMappingColumnFlag',
	'mappingValueFunc',
	'jsonEditorFlag',
	'rowSelect',
	'operatorWidth',
	'funcFlag'
])

const c = [
	{
		title: '编码',
		key: 'fieldCode',
		dataIndex: 'fieldCode',
		slot: 'fieldCode',
		editor: props.isUpdateColumnFlag == null || props.isUpdateColumnFlag ? 'input' : null,
		tree: true
	},
	{
		title: '名称',
		key: 'fieldName',
		dataIndex: 'fieldName',
		editor: props.isUpdateColumnFlag == null || props.isUpdateColumnFlag ? 'input' : null,
		slot: 'fieldName'
	},
	{
		title: '类型',
		key: 'fieldType',
		dataIndex: 'fieldType',
		editor: props.isUpdateColumnFlag == null || props.isUpdateColumnFlag ? 'slot' : null,
		slot: 'fieldType'
	},
	{
		title: '描述',
		key: 'fieldDesc',
		dataIndex: 'fieldDesc',
		editor: props.isUpdateColumnFlag == null || props.isUpdateColumnFlag ? 'input' : null,
		slot: 'fieldDesc'
	},
	{
		title: '数组',
		cellType: props.isUpdateColumnFlag == null || props.isUpdateColumnFlag ? 'checkbox' : null,
		key: 'isArrayFlag',
		dataIndex: 'isArrayFlag',
		slot: 'isArrayFlag',
		mapping: [
			{
				key: true,
				value: '是'
			},
			{
				key: false,
				value: '否'
			}
		]
	}
]

if (props.isMappingColumnFlag) {
	c.push({
		title: '映射值',
		key: 'mappingPath',
		dataIndex: 'mappingPath',
		editor: props.isUpdateColumnFlag == null || props.isUpdateColumnFlag ? 'input' : null,
		slot: 'mappingPath'
	})
}

if (props.funcFlag) {
	c.push({
		title: '函数',
		slot: 'funcFlag',
		dataIndex: 'funcFlag',
		editor: "slot",
		align: 'center'
	})
}
if (props.defaultValueFlag) {
	c.push({
		title: '默认值',
		slot: 'defaultValue',
		dataIndex: 'defaultValue',
		editor: props.isUpdateDefaultValueFlag
			? 'input'
			: props.isUpdateColumnFlag == null || props.isUpdateColumnFlag
				? 'input'
				: null,
		align: 'center'
	})
}

if (props.isActionColumnFlag) {
	c.push({
		title: '操作',
		slot: 'action',
		dataIndex: 'action',
		width: props.operatorWidth || 350,
		fixed: 'right',
		align: 'center',
		buttonList: [
			{
				click: (field, record) => {
					addChildren(record)
				},
				render: (record) => {
					if (props.isAddChildrenColumnFlag == null || props.isAddChildrenColumnFlag) {
						return '子集'
					}
				}
			},
			{
				click: (field, record) => {
					remove(record)
				},
				render: (record) => {
					if (props.isRemoveColumnFlag == null || props.isRemoveColumnFlag) {
						return '删除'
					}
				}
			},
			{
				click: (field, record) => {
					mappingValueNow(record)
				},
				render: (record) => {
					if (!props.isMappingColumnFlag) {
						return null
					}
					if (record.mappingPath) {
						return '取消映射'
					} else {
						return '映射'
					}
				}
			}
		]
	})
}

const paramColumns = ref(c)

const addEmptyHeaders = () => {
	addRow()
}

const addRow = (row) => {
	const id = nanoid(5)
	const d = {
		_key: id,
		fieldCode: null,
		fieldName: null,
		fieldType: null,
		fieldDesc: null,
		defaultValue: null,
		children: null,
		editorFlag: false,
		_showChildren: true,
		isArrayFlag: false
	}
	if (!row) {
		 props.params?.params.push(d)
		///tableRef.value.addRecord(d)
	} else {
		tableRef.value.addChildRecord(row, d)
	}

	// row.push(d);
}

const remove = (record) => {
	tableRef.value.removeByRecord(record)
	 props.params.params = tableRef.value.getRecords();
}

const fieldTypeList = ref([])

const queryFieldTypeList = async () => {
	fieldTypeList.value = await processApi.queryFieldTypeList()
}
const queryFuncList = async () => {
	funcList.value = await processApi.queryFuncList()
}
onMounted(async () => {
	await queryFieldTypeList()
	if(props.funcFlag){
		await queryFuncList()
	}
})

const addChildren = (data) => {
	// const data = repeatDoit(props.params.params, row);
	// data.editorFlag = false;
	if (!data.children) {
		data.children = []
	}
	if (data.fieldType != 'Object') {
		message.error('不是Object类型不能新增子集')
		return
	}
	addRow(data)
}

const viewType = ref(true)

const viewTypeChange = (type) => {
	if (type == 'table') {
		viewType.value = true
	} else {
		viewType.value = false
	}

	// viewType.value = !viewType.value;
	if (!viewType.value) {
		setTimeout(() => {
			initJsonEditor()
		}, 0)
	} else {
		if (!je.value) {
			return
		}
		const value = je.value.getText()
		props.params.params = JSON.parse(value)
	}
}

const jsonEditor = ref()

const je = ref()

const initJsonEditor = () => {
	const options = {
		modes: ['code', 'tree', 'form', 'text', 'preview'],
		mode: 'code'
	}
	je.value = new JsonEditor(jsonEditor.value, options)
	// const initJson = {};
	// editor.value.set(initJson);
	je.value.set(props.params.params || {})
}

const rowClick = (row) => {
	let rowb = cellChange(row)
	clickRow.value = rowb
	Func.clearHiLight(props.params.params)
	//这里需要回调
	if (props.rowSelect) {
		props.rowSelect(clickRow.value)
	}
}

const cellClick = (field, row) => {
	if (field != 'isArrayFlag') {
		return
	}

	row.isArrayFlag = !row.isArrayFlag
}

const cellChange = (row) => {
	//这里需要补全path
	const rootPath = '$'
	const rowb = Func.repeatCompPath(props.params.params, row, rootPath, rootPath)
	return rowb
}

const getSelectRow = () => {
	return clickRow.value
}

const mappingRowHiLight = (mappingValue) => {
	Func.clearHiLight(props.params.params)
	if (!mappingValue) {
		return
	}

	const rootPath = '$'
	Func.repeatCompPath(props.params.params, {}, rootPath, rootPath)

	//从row中找到这个然后添加背景颜色
	const row = Func.findRowByPath(props.params.params, mappingValue)
	if (!row) {
		return
	}
	row.hiLightFlag = true
}

defineExpose({
	getSelectRow,
	mappingRowHiLight,
	repairJson: Func.repairJson,
	repeatCompPath: Func.repeatCompPath
})

const clickRow = ref()
const mappingValueNow = (record) => {
	if (props.mappingValueFunc) {
		if (record.mappingPath) {
			unMappingValueNow(record)
		} else {
			props.mappingValueFunc(clickRow.value)
		}

		tableRef.value.updateRecord(record)
	}
}
const funcList = ref([{
	code: 'func1',
	name: '函数1'
}])

const unMappingValueNow = (row, index) => {
	row.mappingPath = ''
	row.mappingJsonPath = ''
}

const uploadInput = ref()
const importParamDefine = () => {
	const file = uploadInput.value.files[0]
	if (file) {
		const reader = new FileReader()

		reader.onload = (e) => {
			const data = e.target.result
			if (data) {
				paramsCopy(data)
				message.success('导入成功')
			}
		}
		reader.readAsText(file)
	}
}

const paramsCopy = (data) => {
	let d = null

	try {
		d = JSON.parse(data)
	} catch (e) {
	}
	if (!d) {
		message.error('错误的json数据')
		return
	}

	//特征 很明显
	if (d.params && d.basicTypeFlag != null && d.isArrayFlag != null) {
		props.params.params = d.params
		props.params.basicTypeFlag = d.basicTypeFlag
		props.params.isArrayFlag = d.isArrayFlag
	} else {
		//原始json导入

		if (d instanceof Array) {
			props.params.isArrayFlag = true
			d = d[0] //从数组中获取一个元素
		}
		let p = Func.jsonToParamDefine(d)
		if (!p) {
			p = []
		}
		props.params.params = p
	}
}
const exportJsonToFile = () => {
	//把json导出一把
	downloadUtil.downloadFile(JSON.stringify(props.params, null, 2), 'params.json', 'text/plain')
}

const exportJsonToText = () => {
	copyToClip(JSON.stringify(props.params, null, 2))
	message.info('导出到粘贴板成功')
	return true
}

const ztbImportJson = async () => {
	const d = await getClipboardContent()

	if (d) {
		paramsCopy(d)
		message.success('导入成功')
	}
}


const getClipboardContent = async () => {
	try {
		const text = await navigator.clipboard.readText() // 获取粘贴板的文本内容
		return text
	} catch (error) {
		message.error("无法读取粘贴板内容");
	}
}

/**
 * 复制多行内容到粘贴板
 * contentArray: 需要复制的内容（传一个字符串数组）
 * message : 复制完后的提示，不传则默认提示"复制成功"
 */
const copyToClip = (contentArray) => {
	const textarea = document.createElement('textarea')
	textarea.value = contentArray
	document.body.appendChild(textarea)
	textarea.select()
	if (document.execCommand('copy')) {
		document.execCommand('copy')
	}
	document.body.removeChild(textarea)
}

const autoMappingFunc = () => {
	if (props.autoMappingFunc) {
		props.autoMappingFunc(props.params)
	}

	tableRef.value.reRender()
}
const clearMappingFunc = () => {
	clearMapping(props.params.params)
	tableRef.value.reRender()
}
const clearMapping = (data) => {
	for (const b of data) {
		unMappingValueNow(b, 0)
		if (b.children) {
			clearMapping(b.children)
		}
	}
}
const clear = () => {
	props.params.params = []
}
</script>

<template>
	<a-card>
		<a-row justify="end">
			<a-col :span="6">
				<a-space>
					<a-popover title="导入" trigger="click">
						<template #content>
							<a-card :bordered="false">
								<a-space>
									<a-button @click="uploadInput.click()">json定义</a-button>
									<input type="file" ref="uploadInput" @change="importParamDefine"
										   style="display: none"/>
									<a-button @click="ztbImportJson">粘贴板</a-button>
								</a-space>
							</a-card>
						</template>
						<a-button v-show="props.isImportFlag == null || props.isImportFlag" type="primary">导入
						</a-button>
					</a-popover>

					<a-popover title="导出" trigger="click">
						<template #content>
							<a-card :bordered="false">
								<a-space>
									<a-button @click="exportJsonToFile" type="primary">文件</a-button>
									<a-button @click="exportJsonToText">文本</a-button>
								</a-space>
							</a-card>
						</template>
						<a-button>导出</a-button>
					</a-popover>
				</a-space>
			</a-col>

			<a-col :span="18">
				<a-row justify="end">
					<a-space>
						<span v-if="props.isViewAutoMappingFlag">
							<a-button type="primary" @click="autoMappingFunc">AM</a-button>
						</span>
						<span v-if="props.isViewAutoMappingFlag">
							<a-button type="primary" @click="clearMappingFunc">CM</a-button>
						</span>
						<span>
							<a-checkbox v-model:checked="props.params.isArrayFlag" v-show="props.isViewArrayFlag"
										size="small"
							>数组</a-checkbox
							>
						</span>
						<span v-if="props.isViewBasicFieldFlag">
							<a-checkbox v-model:checked="props.params.basicTypeFlag"
										size="small"> 基本数据类型 </a-checkbox>
						</span>
						<span
							v-if="!props.params.basicTypeFlag && (props.isAddColumnFlag == null || props.isAddColumnFlag)">
							<a-button type="primary" @click="addEmptyHeaders">新增 </a-button>
						</span>
						<span v-if="!props.params.basicTypeFlag && props.isClearFlag">
							<a-button type="primary" @click="clear">清空</a-button>
						</span>
						<span v-if="!props.params.basicTypeFlag">
							<a-tag @click="viewTypeChange('table')">table</a-tag>
						</span>
						<span v-if="!props.params.basicTypeFlag && jsonEditorFlag">
							<a-tag @click="viewTypeChange('json')">json</a-tag>
						</span>
					</a-space>
				</a-row>
			</a-col>
		</a-row>
		<a-row justify="start" v-if="props.params?.basicTypeFlag">
			<a-col :span="24">
				<a-select v-model:value="props.params.basicFieldType" clearable filterable>
					<a-select-option v-for="item in fieldTypeList" :label="item.name" :value="item.code"
									 :key="item.code"/>
				</a-select>
			</a-col>
		</a-row>

		<a-row justify="start" style="margin-top: 4px" v-if="!props.params?.basicTypeFlag">
			<a-col :span="24">
				<span v-if="viewType">
					<h-table
						ref="tableRef"
						:rowClick="rowClick"
						:cellClick="cellClick"
						:cellChange="cellChange"
						:columns="paramColumns"
						:data="props.params?.params"
					>
						<template #fieldType:editor="{ record }">
							<a-select v-model:value="record.fieldType" style="width: 100%; height: 100%" clearable
									  filterable>
								<a-select-option v-for="item in fieldTypeList" :label="item.name" :value="item.code"
												 :key="item.code"/>
							</a-select>
						</template>
						<template #funcFlag:editor="{ record }">
							<a-select v-model:value="record.funcList" style="width: 100%; height: 100%" clearable
							mode="tags"  filterable>
								<a-select-option v-for="item in funcList" :label="item.name" :value="item.code"
												 :key="item.code"/>
							</a-select>
						</template>
					</h-table>
				</span>
				<span v-if="!viewType">
					<div class="jsoneditor" ref="jsonEditor" style="width: 100%; height: 600px"></div>
				</span>
			</a-col>
		</a-row>
	</a-card>
</template>

<style scoped>
.hilight {
	border: 5px solid transparent;
	border-top: 1px solid #46cc46;
	border-radius: 25%;
}
</style>
